﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace BLServer
{    
		[DataContract(Namespace="http://Testy.Types.Data")]	
    public class Project
    {
        public Project() 
        {
            ID = Guid.NewGuid().ToString();
        }
        public Project(string name, bool isHead)
        {
            ID = Guid.NewGuid().ToString();
            Name = name;
            IsHead = isHead;
        }

        [DataMember]
        public string ID { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public bool IsHead { get; set; }

        [DataMember]
        public List<Project> Subprojects { get; set; }

        [DataMember]
        public List<string> IssuesIDs { get; set; }

        public override string ToString()
        {
            return Name;
        }
        
        public Project GetSubprojectByIDRecurse(string projectID)
        {
            if (Subprojects != null)
            {
                List<Project> projCurrent = new List<Project>();
                projCurrent.AddRange(Subprojects);
                List<Project> temp = new List<Project>();
                bool stopSearch = false;
                Project projFound = null;
                while ((projCurrent.Count != 0) && (!stopSearch))
                {
                    temp.Clear();
                    foreach (Project prIn in projCurrent)
                    {
                        if (prIn.ID == projectID)
                        {
                            stopSearch = true;
                            projFound = prIn;
                            break;
                        }
                        if (prIn.Subprojects != null)
                            temp.AddRange(prIn.Subprojects);
                    }
                    projCurrent.Clear();
                    projCurrent.AddRange(temp);
                }
                return projFound;
            }
            else return null;
        }

        public Project GetParentOfSubprojectRecurse(string subprojectID)
        {            
            if (Subprojects != null)
            {
                List<Project> projCurrent = new List<Project>();
                projCurrent.AddRange(Subprojects);
                List<Project> temp = new List<Project>();
                bool stopSearch = false;
                Project projFound = null;
                if ((from Project p in projCurrent where p.ID == subprojectID select p).Count<Project>() == 1)
                {
                    stopSearch = true;
                    projFound = this;
                }                
                while ((projCurrent.Count != 0) && (!stopSearch))
                {
                    temp.Clear();                    
                    foreach (Project prIn in projCurrent)
                    {
                        if (prIn.Subprojects != null)
                        {
                            if ((from Project p in prIn.Subprojects where p.ID == subprojectID select p).Count<Project>() == 1)
                            {
                                stopSearch = true;
                                projFound = prIn;
                                break;
                            }
                            temp.AddRange(prIn.Subprojects);
                        }
                    }
                    projCurrent.Clear();
                    projCurrent.AddRange(temp);
                }
                return projFound;
            }
            else return null;
        }

        public List<Project> GetAllSubprojectsRecurse(bool withThis)
        {
            List<Project> tempTotal = new List<Project>();
            if (withThis) tempTotal.Add(this);
            if (Subprojects != null)
            {                
                tempTotal.AddRange(Subprojects);
                List<Project> temp = new List<Project>();
                temp.AddRange(Subprojects);
                List<Project> temp2 = new List<Project>();
                temp2.AddRange(Subprojects);
                while (temp2.Count != 0)
                {
                    temp2.Clear();
                    foreach (Project pr in temp)
                    {
                        if (pr.Subprojects != null) 
                            temp2.AddRange(pr.Subprojects);
                    }
                    tempTotal.AddRange(temp2);
                    temp.Clear();
                    temp.AddRange(temp2);
                }                
            }

            return tempTotal;
        }

        public List<string> GetAllSubprojectIssueIDsRecurse(bool withThis, List<Project> subprojs)
        {
            List<Project> prj = null;
            if (subprojs == null)
                prj = GetAllSubprojectsRecurse(withThis);
            else prj = subprojs;

            List<string> ids = new List<string>();
            foreach (Project p in prj)
            {
                if (p.IssuesIDs != null)
                    ids.AddRange(p.IssuesIDs);
            }
            return ids;
        }
    }

    [DataContract(Namespace = "http://Testy.Types.Data")]
    public class ProjectIssue
    {
        public ProjectIssue()
        {
            ID = Guid.NewGuid().ToString();
        }
        public ProjectIssue(string name)
        {
            ID = Guid.NewGuid().ToString();
            Name = name;
            IssueType = ProjectIssueType.Bug; //default value
        }

        public ProjectIssue(string name, ProjectIssueType issueType)
        {
            ID = Guid.NewGuid().ToString();
            Name = name;
            IssueType = issueType;
        }

        [DataMember]
        public string ID { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public ProjectIssueType IssueType { get; set; }

        [DataMember]
        public List<ProjectIssueDetail> Details { get; set; }

        [DataMember]
        public Dictionary<string, PersonIssueRole> Persons { get; set; }

        public override string ToString()
        {
            string typeS = Enum.GetName(typeof(ProjectIssueType), IssueType);
            while (typeS.Length < 5) typeS = typeS + ' ';
            return typeS + Name;
        }
    }

    [DataContract(Namespace = "http://Testy.Types.Data")]
    public class ProjectIssueDetail
    {
        public ProjectIssueDetail() { }
        public ProjectIssueDetail(DateTime date, string info)
        {
            Date = date;
            Info = info;
        }

        [DataMember]
        public DateTime Date { get; set; }

        [DataMember]
        public string Info { get; set; }
    }

    [DataContract(Namespace = "http://Testy.Types.Data")]
    public class User
    {
        public User()
        {
            ID = Guid.NewGuid().ToString();
        }
        public User(string name, string password)
        {
            ID = Guid.NewGuid().ToString();
            Name = name;
            Password = password;
            Role = PersonRole.Worker; //default
        }

        [DataMember]
        public string ID { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public string Password { get; set; }

        [DataMember]
        public PersonRole Role { get; set; }

        public override string ToString()
        {
            return Name;
        }

        public static User PasswordlessClone(User original)
        {
            return new User() { ID = original.ID, Name = original.Name, Password = "", Role = original.Role };
        }
    }

    [DataContract(Namespace = "http://Testy.Types.Data")]
    public enum ProjectIssueType
    {
        [EnumMember]
        ToDo,
        [EnumMember]
        Idea,
        [EnumMember]
        Bug
    }

    [DataContract(Namespace = "http://Testy.Types.Data")]
    public enum PersonIssueRole 
    { 
        [EnumMember]
        Admin,
        [EnumMember]
        Reporter,
        [EnumMember]
        None //without role - to avoid removing user from issue
    };

    [DataContract(Namespace = "http://Testy.Types.Data")]
    public enum PersonRole 
    {
        [EnumMember]
        Admin,
        [EnumMember]
        Worker 
    };

		/*
    [DataContract(Namespace = "http://Testy.Types.Data")]
    public class PostDataSet
    {
        public PostDataSet() { }
        public PostDataSet(CommandList command, List<object> parameters)
        {
            Command = command;
            Parameters = parameters;
        }

        [DataMember]
        public CommandList Command { get; set; }

        [DataMember]
        public List<object> Parameters { get; set; }
    }

    public enum CommandList 
    { 
        login, 
        getissues, 
        getprojects,
        getusers
    };
		*/
}
